<template>
  <div class="w-full">
    <a-form
      ref="formRef"
      :model="modelForm"
      :label-col="props.labelCol"
      :wrapper-col="props.wrapperCol"
      @finish="onFinish"
      @finish-failed="onFinishFailed"
    >
      <a-row :gutter="24">
        <template v-for="(item, index) in props.dataSource" :key="index">
          <a-col v-if="!item.vIf || (item.vIf && item.vIf(modelForm))" v-bind="item.colProps">
            <a-form-item :name="item.field" :label="item.label" :rules="item.rules">
              <a-input
                v-if="item.component === ComponentsTypeEnum.Input"
                v-model:value="modelForm[item.field]"
                v-bind="item.componentProps"
                :placeholder="`请输入${item.label}`"
              />
              <a-input-password
                v-if="item.component === ComponentsTypeEnum.InputPassword"
                v-model:value="modelForm[item.field]"
                v-bind="item.componentProps"
                :placeholder="`请输入${item.label}`"
              />
              <a-textarea
                v-if="item.component === ComponentsTypeEnum.InputTextarea"
                v-model:value="modelForm[item.field]"
                v-bind="item.componentProps"
                :placeholder="`请输入${item.label}`"
              />
              <a-select
                v-if="item.component === ComponentsTypeEnum.Select"
                v-model:value="modelForm[item.field]"
                v-bind="item.componentProps"
                :placeholder="`请选择${item.label}`"
                allow-clear
                @change="
                  (value) => {
                    modelForm[item.field] = value;
                  }
                "
              >
              </a-select>
              <a-radio-group
                v-if="item.component === ComponentsTypeEnum.RadioGroup"
                v-model:value="modelForm[item.field]"
                v-bind="item.componentProps"
                :placeholder="`请选择${item.label}`"
                allow-clear
              >
              </a-radio-group>
              <a-checkbox-group
                v-if="item.component === ComponentsTypeEnum.CheckBoxGroup"
                v-model:value="modelForm[item.field]"
                v-bind="item.componentProps"
                :placeholder="`请选择${item.label}`"
                allow-clear
              >
              </a-checkbox-group>
              <UploadImage
                v-if="item.component === ComponentsTypeEnum.Upload"
                :image-str="modelForm[item.field]"
                :component-props="item.componentProps"
                @on-change-upload="
                  (value) => {
                    modelForm[item.field] = value || '';
                  }
                "
              ></UploadImage>
              <div
                v-if="item.component === ComponentsTypeEnum.Tree"
                class="w-full flex items-start justify-between"
              >
                <a-tree
                  ref="treeRef"
                  v-model:checkedKeys="modelForm[item.field]"
                  v-bind="item.componentProps"
                  v-model:expanded-keys="expandedKeys"
                  :check-strictly="checkStrictly"
                  allow-clear
                  auto-expand-parent
                >
                  <template #title="{ title }">
                    {{ title }}
                  </template>
                </a-tree>
                <a-space
                  v-if="item?.componentProps?.treeData.length > 0"
                  class="items-end"
                  direction="vertical"
                >
                  <a-button type="primary" @click="expandHandle(item?.componentProps?.treeData)">
                    {{ expandAll ? '收起' : '展开' }}
                  </a-button>
                  <a-button
                    v-if="!item?.componentProps?.checkStrictly"
                    type="primary"
                    @click="handleChangeCheckStrictly(item.field, item?.componentProps?.treeData)"
                  >
                    {{ checkStrictly ? '父子联动' : '父子不联动' }}
                  </a-button>
                </a-space>
              </div>
              <a-tree-select
                v-if="item.component === ComponentsTypeEnum.TreeSelect"
                v-model:value="modelForm[item.field]"
                :placeholder="`请选择${item.label}`"
                v-bind="item.componentProps"
                allow-clear
              />
              <a-switch
                v-if="item.component === ComponentsTypeEnum.ASwitch"
                v-model:checked="modelForm[item.field]"
                v-bind="item.componentProps"
              />
              <IconsSelect
                v-if="item.component === ComponentsTypeEnum.IconsSelect"
                v-model:value="modelForm[item.field]"
              />
              <tinymce-editor
                v-if="item.component === ComponentsTypeEnum.TinymceEditor"
                v-model:value="modelForm[item.field]"
                v-bind="item.componentProps"
              />
            </a-form-item>
          </a-col>
        </template>
        <slot></slot>
      </a-row>
      <a-row>
        <a-col :span="24" style="text-align: center">
          <a-button class="mx-8px" @click="onCancel">取消</a-button>
          <a-button type="primary" html-type="submit">提交</a-button>
        </a-col>
      </a-row>
    </a-form>
  </div>
</template>

<script setup lang="tsx">
  import UploadImage from '@/components/uploadImage/index.vue';
  import { ComponentsTypeEnum } from '@/enums/componentsEnum';
  import { getTreeKeys, IS_DEV } from '@/utils/common';
  import IconsSelect from '@/components/basic/icons-select/index.vue';
  import TinymceEditor from '@/components/tinymceEditor/index.vue';

  const props = defineProps({
    labelCol: {
      type: Object,
      default: () => {
        return {
          span: 6,
        };
      },
    },
    wrapperCol: {
      type: Object,
      default: () => {
        return {
          span: 14,
        };
      },
    },
    dataSource: {
      type: Object,
      required: true,
      default: () => {
        return {};
      },
    },
    modelData: {
      type: Object,
      required: true,
    },
  });
  const formRef = ref(null);
  const treeRef = ref(null);
  const { modelData } = toRefs(props);
  const expandAll = ref(false);
  const checkStrictly = ref(true);
  const expandedKeys = ref<number[]>([]);
  const modelForm = ref({});
  const emit = defineEmits(['submitForm', 'cancel']);
  const onFinish = (values) => {
    emit('submitForm', values);
  };
  const onCancel = () => {
    emit('cancel');
  };
  const onFinishFailed = (errorInfo) => {
    if (IS_DEV) console.info('Failed: ', errorInfo);
  };
  watchEffect(() => {
    modelForm.value = modelData.value;
  });

  const expandHandle = (treeData) => {
    expandAll.value = !expandAll.value;
    if (expandAll.value) {
      expandedKeys.value = getTreeKeys(treeData);
    } else {
      expandedKeys.value = [];
    }
  };

  const handleChangeCheckStrictly = (field, treeData) => {
    checkStrictly.value = !checkStrictly.value;
    const curCheckedKeys = modelForm.value[field];
    const checkedKeysArray = Array.isArray(curCheckedKeys)
      ? curCheckedKeys
      : curCheckedKeys.checked;
    const checkedKeys = new Set(checkedKeysArray.filter((item) => !!item));
    // 重新设置选中的节点, 保持选中状态与页面显示一致
    if (checkStrictly.value) {
      // 父子联动切换到父子不联动，检查所有的子级节点
      const addChildrenKeys = (nodes) => {
        for (const node of nodes) {
          if (checkedKeys.has(node.id) && node.children) {
            node.children.forEach((child) => {
              if (!checkedKeys.has(child.id)) {
                checkedKeys.add(child.id);
              }
            });
          }
          if (node.children) {
            addChildrenKeys(node.children);
          }
        }
      };
      addChildrenKeys(treeData);
    } else {
      // 父子不联动切换到父子联动
      const checkAllChildrenSelected = (node) => {
        return node.children.every((child) => {
          // 检查child是否被选中，或者它有子级且所有子级是否被选中
          return checkedKeys.has(child.id) || (child.children && checkAllChildrenSelected(child));
        });
      };
      // 检查所有的父级节点
      const addParentKeys = (nodes) => {
        for (const node of nodes) {
          if (node.children && checkAllChildrenSelected(node)) {
            if (!checkedKeys.has(node.id)) {
              checkedKeys.add(node.id);
            }
          }
          if (node.children) {
            addParentKeys(node.children);
          }
        }
      };
      addParentKeys(treeData);
    }
    modelForm.value[field] = checkedKeys.size > 0 ? { checked: [...checkedKeys] } : [];
  };
</script>

<style scoped lang="less">
  @import '@/styles/animation.less';
  :deep(.ant-btn) {
    .throttle_animation();
  }
</style>
